跳到主要内容

Casbin 的 ACL 模型

ACL 模型

ACL(access-control-list,访问控制列表)。ACL显示定义了每个主体对每个资源的权限情况,未定义的就没有权限。

首先编写模型文件:

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act

[policy_effect]
e = some(where (p.eft == allow))

上面模型文件规定了权限由 sub,obj,act 三要素组成,只有在策略列表中有和它完全相同的策略时,该请求才能通过。

匹配器的结果可以通过 p.eft 获取,some(where (p.eft == allow)) 表示只要有一条策略允许即可。

然后我们策略文件(即谁能对什么资源进行什么操作):

p, dajun, data1, read
p, lizi, data2, write

上面 policy.csv 文件的两行内容表示

  • dajun 对数据 data1 有 read 权限
  • lizi 对数据 data2 有 write 权限

接下来就是使用的代码:

package main

import (
"fmt"
"log"

"github.com/casbin/casbin/v2"
)

func check(e *casbin.Enforcer, sub, obj, act string) {
ok, _ := e.Enforce(sub, obj, act)
if ok {
fmt.Printf("%s CAN %s %s\n", sub, act, obj)
} else {
fmt.Printf("%s CANNOT %s %s\n", sub, act, obj)
}
}

func main() {
e, err := casbin.NewEnforcer("./model.conf", "./policy.csv")
if err != nil {
log.Fatalf("NewEnforecer failed:%v\n", err)
}

check(e, "dajun", "data1", "read")
check(e, "lizi", "data2", "write")
check(e, "dajun", "data1", "write")
check(e, "dajun", "data2", "read")
}

执行

$ go run main.go
dajun CAN read data1
lizi CAN write data2
dajun CANNOT write data1
dajun CANNOT read data2

我们还可以加上超级管理员,超级管理员可以进行任何操作。假设超级管理员为root,我们只需要修改匹配器:

[matchers]
e = r.sub == p.sub && r.obj == p.obj && r.act == p.act || r.sub == "root"

因为 sub = "root" 时,匹配器一定能通过

func main() {
e, err := casbin.NewEnforcer("./model.conf", "./policy.csv")
if err != nil {
log.Fatalf("NewEnforecer failed:%v\n", err)
}

check(e, "root", "data1", "read")
check(e, "root", "data2", "write")
check(e, "root", "data1", "execute")
check(e, "root", "data3", "rwx")
}